package serivces

import (
	"context"
	"errors"
	"github.com/go-redis/redis/v8"
	"tcp_server/src/common_util"
	"tcp_server/src/config"
	"tcp_server/src/dao"
	"time"
)

// TokenAuthService Token 认证服务
type TokenAuthService struct{}

// NewTokenAuthService 创建一个新的 Token 认证服务实例
func NewTokenAuthService() *TokenAuthService {
	return &TokenAuthService{}
}

// TokenAuthentication Token 认证方法 1代表成功认证，0代表认证失败 ，-1代表 服务器出现异常
func (s *TokenAuthService) TokenAuthentication(args ...interface{}) (interface{}, error) {

	if len(args) < 2 {
		common_util.ErrorLogger.Printf("TokenAuthentication 方法被调用传入的参数不足: %v", args)
		return nil, errors.New("调用TokenAuthentication 方法所需要参数不足")
	}

	username, ok1 := args[0].(string)
	token, ok2 := args[1].(string)

	if !ok1 || !ok2 {
		common_util.ErrorLogger.Printf("TokenAuthentication 方法被调用传入的参数类型有误：%v", args)
		return nil, errors.New("调用TokenAuthentication 方法所需要参数类型转换错误（所需类型为 string）")
	}
	redisTokenKey := config.RedisUserTokenKey + username
	redisClient := config.Redis
	redisTokenValue, err := redisClient.Get(context.Background(), redisTokenKey).Result()
	if err != nil && !errors.Is(err, redis.Nil) {
		common_util.ErrorLogger.Printf("查询 Redis 出现失败 ： %v", err)
		return -1, nil
	}
	// 鉴权成功
	if redisTokenValue == token {
		return 1, nil
	}
	tokenModel, mysqlErr := dao.GetTokenByUserName(username)
	if mysqlErr != nil {
		common_util.ErrorLogger.Printf("查询 MySQL 出现失败 ： %v", err)
		return -1, nil
	}
	// 鉴权失败
	if tokenModel.Token != token {
		return 0, nil
	}

	// 刷新回Redis
	tokenExpireTime := time.Until(tokenModel.ExpireTime)
	if err := redisClient.Set(context.Background(), redisTokenKey, token, tokenExpireTime).Err(); err != nil {
		common_util.ErrorLogger.Printf("Token缓存到Redis中出现错误：%v", err)
	}
	return 1, nil
}
